﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Netfraction.Network.Protocol.BASE.Handler
{
    public class HandlerSUP : ProtocolMessageActionHandler
    {
        public HandlerSUP()
            : base()
        {
            mParameterCodes = new List<string>(new string[] {"AD", "RM"});

            mSupportedConnectionStates = new List<RemoteMachine.ConnectionState>();
            mSupportedConnectionStates.Add(RemoteMachine.ConnectionState.Protocol);
            mSupportedConnectionStates.Add(RemoteMachine.ConnectionState.Normal);
        }

        #region ProtocolMessageActionHandler Members

        public override string ProtocolActionCode
        {
            get { return "SUP"; }
        }

        public override bool HandleProtocolMessage(RemoteMachine.Node node, ProtocolMessage message, IEnumerable<ProtocolFeature> extenders)
        {
            // ISUP ADBASE ADTIGR ADPING - uHub
            // CSUP ADBAS0 ADBASE ADTIGR ADBZIP ADZLIG - apexDC++
            if (IsSupportedConnectionState(node))
            {
                if (message.Parameters.Count != 0)
                {
                    message.Parameters = DecodeParameters(message.Parameters);

                    LocalMachine.Client client = LocalMachine.Client.GetInstance();

                    lock (client)
                    {
                        var adders = from p in message.Parameters
                                     where p.ParameterCode == "AD"
                                     select p;
                        System.Diagnostics.Debug.WriteLine(adders.Count());
                        foreach (ProtocolParameter param in adders/*message.GETParameterOptions.Where(mC => mC.ParameterCode == "AD")*/)
                        {
                            // check if client supports feature && feature isn't in hub feature list already
                            if (client.Features.ContainsKey(param.ParameterValue) && !node.Features.ContainsKey(param.ParameterValue))
                            {
                                node.Features.Add(param.ParameterValue, client.Features[param.ParameterValue]);
                            }
                        }
                        foreach (ProtocolParameter param in message.Parameters.Where(c => c.ParameterCode == "RM"))
                        {
                            node.Features.Remove(param.ParameterValue);
                        }

                        // Initialise the session hash algorithm
                        // We cannot assume that just because we connect to the hub with TIGR that all other clients connect with TIGR
                        // Thus, because a client may be using a different hashing algorithm, this method should Init the Session Hash
                        // for the Remote Peer, not the local client
                        if (node.SessionHashAlgorithm == null)
                        {
                            foreach (ProtocolParameter param in adders)
                            {
                                // check that both support the feature
                                if (client.Features.ContainsKey(param.ParameterValue) && node.Features.ContainsKey(param.ParameterValue))
                                {
                                    if (node.Features[param.ParameterValue] is IProtocolHashFeature)
                                    {
                                        node.SessionHashAlgorithm = (node.Features[param.ParameterValue] as IProtocolHashFeature).GetHashAlgorithm();
                                        client.InitializeClientId(node.SessionHashAlgorithm);

                                        // only use the first algorithm detected
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (node is RemoteMachine.Peer)
                    {
                        node.Connection.State = RemoteMachine.ConnectionState.Identify;
                    }
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion
    }
}
